package com.ruoyi.framework.config;

import com.github.xiaoymin.swaggerbootstrapui.annotations.EnableSwaggerBootstrapUI;
import com.google.common.collect.Lists;
import com.ruoyi.common.enums.ExceptionEnum;
import com.ruoyi.framework.config.properties.SwaggerProperties;
import io.swagger.annotations.ApiOperation;
import io.swagger.models.auth.In;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RequestMethod;
import springfox.documentation.builders.*;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.*;


@Configuration
@EnableSwagger2
@EnableSwaggerBootstrapUI
public class Swagger2Config {

    @Autowired
    private SwaggerProperties swaggerProperties;

    @Bean(value = "adminApi")
    public Docket adminApi() {
        ParameterBuilder parameterBuilder = new ParameterBuilder();
        List<Parameter> parameters = Lists.newArrayList();
        parameterBuilder.name("Authorization").description("token令牌").modelRef(new ModelRef("String")).parameterType("header").required(false).build();
        parameters.add(parameterBuilder.build());
        Docket docket = new Docket(DocumentationType.SWAGGER_2).useDefaultResponseMessages(false).consumes(initConsumes()).produces(initProduces())
                .globalResponseMessage(RequestMethod.POST, initResponseCode())
                .apiInfo(apiInfo())
                .groupName("后台管理")
                .select()
                // 扫描所有有注解的api，用这种方式更灵活
                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .paths(PathSelectors.any())
                .build().globalOperationParameters(parameters)
                // 设置安全模式，swagger可以设置访问token
//                .securitySchemes(securitySchemes())
//                .securityContexts(Lists.newArrayList(securityContext()))
                .pathMapping(swaggerProperties.getPathMapping());
        return docket;
    }

    /**
     * 安全模式，这里指定token通过Authorization头请求头传递
     */
    private List<SecurityScheme> securitySchemes()
    {
        List<SecurityScheme> apiKeyList = new ArrayList<SecurityScheme>();
        apiKeyList.add(new ApiKey("Authorization", "Authorization", In.HEADER.toValue()));
        return apiKeyList;
    }

    /**
     * 获取apiInfo
     *
     * @return
     */
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title(swaggerProperties.getTitle())
                // 描述
                .description("CDN平台接口文档")
                // 作者信息
                .contact(new Contact("经纬线", null, null))
                .termsOfServiceUrl(swaggerProperties.getUrl())
                .version(swaggerProperties.getVersion())
                .build();
    }

    // 定义全局相应状态码
    private List<ResponseMessage> initResponseCode() {
        List<ResponseMessage> responseMessageList = new ArrayList<>();
        Arrays.stream(ExceptionEnum.values()).forEach(errorEnum -> {
            responseMessageList.add(
                    new ResponseMessageBuilder().code(errorEnum.getCode()).message(errorEnum.getMsg()).responseModel(
                            new ModelRef(errorEnum.getMsg())).build()
            );
        });
        return responseMessageList;
    }

    // 定义全局请求参数类型
    private Set<String> initConsumes() {
        Set<String> sets = new HashSet<>();
        sets.add("application/x-www-form-urlencoded");
        return sets;
    }

    // 定义全局返回数据类型
    private Set<String> initProduces() {
        Set<String> sets = new HashSet<>();
        sets.add("application/json");
        return sets;
    }

    /**
     * 安全上下文
     */
    private SecurityContext securityContext() {
        return SecurityContext.builder()
                .securityReferences(defaultAuth())
                .forPaths(PathSelectors.regex("/.*"))
                .build();
    }

    /**
     * 默认的安全上引用
     */
    List<SecurityReference> defaultAuth() {
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        return Lists.newArrayList(new SecurityReference("Authorization", authorizationScopes));
    }
}